home *** CD-ROM | disk | FTP | other *** search
- /* Loading of .O files */
-
- #include "params.h"
- #include "gambit.h"
- #include "struct.h"
- #include "os.h"
- #include "mem.h"
- #include "strings.h"
- #include "opcodes.h"
- #include "run.h"
- #include "stats.h"
- #include "emul.h"
-
-
- /*---------------------------------------------------------------------------*/
-
-
- struct patch_rec {
- struct patch_rec *next; /* next entry in the patch list */
- long index; /* index to value's source */
- SCM_obj *loc; /* pointer to location to patch to */
- };
-
- typedef struct patch_rec *PATCH_PTR;
-
-
- char *alloc_ptr, *read_bot, *read_top, *load_bot, *load_top, *load_ptr;
- SCM_obj *object;
- PATCH_PTR free_patches, prim_patches;
- char *filename, *procedure_name;
-
-
- char *alloc( len )
- long len;
- { long len2 = ceiling8( len );
- if (alloc_ptr-len2 < read_top)
- { os_err = "Load memory overflow"; return NULL; }
- alloc_ptr -= len2;
- return alloc_ptr;
- }
-
-
- long begin_load()
- { free_patches = NULL;
- prim_patches = NULL;
- read_bot = pstate->heap_old;
- alloc_ptr = read_bot + (pstate->heap_mid - pstate->heap_bot);
- read_top = read_bot;
- object = (SCM_obj *)alloc( sizeof(SCM_obj) * (long)MAX_NB_OBJECTS_PER_FILE );
- return (object == NULL);
- }
-
-
- long end_load()
- { PATCH_PTR patch = prim_patches;
- while (patch != NULL)
- { SCM_obj val = sstate->globals[patch->index].value;
- if (val == (long)SCM_unbound)
- { os_err = string_append( "Undefined primitive, ",
- global_name(patch->index) );
- return 1;
- }
- *(patch->loc) += val; /* patch up reference to the primitive */
- patch = patch->next;
- }
- return 0;
- }
-
-
- long eof()
- { os_err = "Premature EOF";
- return 1;
- }
-
-
- #define load_long_word(var) \
- { if (load_ptr+4>load_top) return eof(); var = *(long *)load_ptr; load_ptr += 4; }
-
- #define load_word(var) \
- { if (load_ptr+2>load_top) return eof(); var = *(short *)load_ptr; load_ptr += 2; }
-
- #define load_words( n, ptr ) \
- { register long i = (n); register short *pt = (ptr); \
- if (load_ptr + i*2 > load_top) return eof(); \
- while (i>0) { *(pt++) = *(short *)load_ptr; load_ptr += 2; i--; } \
- }
-
-
- long load_string( str )
- char **str;
- { *str = load_ptr;
- while (*(load_ptr++) != '\0') if (load_ptr > load_top) return eof();
- load_ptr = (char *)ceiling2( load_ptr );
- if (load_ptr > load_top) return eof();
- return 0;
- }
-
-
- long skip_string( offset )
- long *offset;
- { *offset = load_ptr - load_bot;
- while (*(load_ptr++) != '\0') if (load_ptr > load_top) return eof();
- load_ptr = (char *)ceiling2( load_ptr );
- if (load_ptr > load_top) return eof();
- return 0;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
-
- long nb_objects, highest_object, nb_symbols;
- PATCH_PTR object_patches, M68020_patches, M68881_patches;
-
-
- long add_object( value )
- SCM_obj value;
- { long i = nb_objects++;
- if (i + nb_symbols >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Too many objects in an object file"; return 1; }
- object[i] = value;
- return 0;
- }
-
-
- long add_patch( list, index, loc )
- PATCH_PTR *list;
- long index;
- SCM_obj *loc;
- { PATCH_PTR patch;
- if (free_patches != NULL)
- { patch = free_patches;
- free_patches = free_patches->next;
- }
- else
- { patch = (PATCH_PTR)alloc( (long)sizeof(struct patch_rec) );
- if (patch == NULL) return 1;
- }
- patch->next = *list;
- patch->index = index;
- patch->loc = loc;
- *list = patch;
- return 0;
- }
-
-
- long add_prim_patch( index, loc )
- long index;
- SCM_obj *loc;
- { return add_patch( &prim_patches, index, loc );
- }
-
-
- long add_object_patch( index, loc )
- long index;
- SCM_obj *loc;
- { if (index + nb_symbols >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Object reference too big"; return 1; }
- if (index > highest_object) highest_object = index;
- return add_patch( &object_patches, index, loc );
- }
-
-
- long patchup_M68020_emul_code()
- { PATCH_PTR patch = M68020_patches;
- while (patch != NULL)
- { PATCH_PTR next = patch->next;
- if (emul_M68020_instr( (short *)patch->loc )) return 1;
- patch->next = free_patches;
- free_patches = patch;
- patch = next;
- }
- return 0;
- }
-
-
- long patchup_M68881_emul_code()
- { PATCH_PTR patch = M68881_patches;
- while (patch != NULL)
- { PATCH_PTR next = patch->next;
- if (emul_M68881_instr( (short *)patch->loc )) return 1;
- patch->next = free_patches;
- free_patches = patch;
- patch = next;
- }
- return 0;
- }
-
-
- long load_sym( i, loc )
- short i;
- SCM_obj *loc;
- { if (i == INDEX_MASK)
- { char *name;
- long j = nb_symbols++;
- if (j + nb_objects >= (long)MAX_NB_OBJECTS_PER_FILE)
- { os_err = "Too many symbols in an object file"; return 1; }
- if (load_string( &name )) return 1;
- if (alloc_symbol( name, loc )) return 1;
- object[MAX_NB_OBJECTS_PER_FILE-1-j] = *loc;
- }
- else if (i > nb_symbols)
- { os_err = "Symbol reference out of range"; return 1; }
- else
- *loc = object[MAX_NB_OBJECTS_PER_FILE-1-i];
- return 0;
- }
-
-
- long load_value( loc )
- SCM_obj *loc;
- { long val, masked;
- load_long_word( val );
- masked = val & ~(((long)INDEX_MASK) << 3);
- if (masked == (long)OBJECT)
- { *loc = (SCM_obj)0;
- if (add_object_patch( (val >> 3) & INDEX_MASK, loc )) return 1;
- }
- else if (masked == (long)SYMBOL)
- { if (load_sym( (short)((val >> 3) & INDEX_MASK), loc )) return 1;
- }
- else if (masked == (long)PRIM_PROC)
- { SCM_obj sym;
- long index;
- if (load_sym( (short)((val >> 3) & INDEX_MASK), &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- if (add_prim_patch( index, loc )) return 1;
- *loc = (SCM_obj)0;
- }
- else
- *loc = (SCM_obj)val;
- return 0;
- }
-
-
- long load_proc( proc_adr, len, name )
- SCM_obj proc_adr;
- long len;
- char *name;
- { short *code_ptr = (short *)proc_adr;
-
- procedure_name = name;
-
- M68020_patches = NULL;
- M68881_patches = NULL;
-
- while (1)
- { short tag;
-
- load_word( tag );
-
- if (tag > 0)
- { load_words( tag, code_ptr );
- code_ptr += tag;
- }
-
- else if (tag == (short)PADDING_TAG)
- /* just skip */;
-
- else if (tag == (short)END_OF_CODE_TAG)
- break;
-
- else if (tag == (short)M68020_TAG)
- { if (!os_M68020)
- if (add_patch( &M68020_patches, 0L, (SCM_obj *)code_ptr )) return 1;
- }
-
- else if (tag == (short)M68881_TAG)
- { if (!os_M68881)
- if (add_patch( &M68881_patches, 0L, (SCM_obj *)code_ptr )) return 1;
- }
-
- else if (tag == (short)STAT_TAG)
- { long index;
- if (alloc_stat( &index ))
- { os_err = "Statistics table overflow"; return 1; }
- else
- { *(long **)code_ptr = &pstate->stats_counters[index];
- code_ptr += 2;
- if (skip_string( &sstate->stats_offsets[index] )) return 1;
- }
- }
-
- else
- { short i = tag & INDEX_MASK;
- tag = tag & ~INDEX_MASK;
-
- if (tag == (short)PROC_REF_TAG)
- { if (add_object_patch( (long)i, (SCM_obj *)code_ptr )) return 1;
- load_word( *(long *)code_ptr );
- code_ptr += 2;
- }
-
- else if (tag == (short)GLOBAL_VAR_REF_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].value );
- }
-
- else if (tag == (short)GLOBAL_VAR_SET_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].value );
- *(code_ptr++) = LEAA6_DISP_A1_OP;
- *(code_ptr++) = table_offset( &sstate->tramps[index] );
- *(code_ptr++) = MOVE_L_A1_A6_DISP_OP;
- *(code_ptr++) = table_offset( &sstate->globals[index].jump_adr );
- }
-
- else if (tag == (short)GLOBAL_VAR_REF_JUMP_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- *(code_ptr++) = table_offset( &sstate->globals[index].jump_adr );
- }
-
- else if (tag == (short)PRIM_REF_TAG)
- { SCM_obj sym;
- long index;
- if (load_sym( i, &sym )) return 1;
- if (alloc_global_from_symbol( sym, &index )) return 1;
- if (add_prim_patch( index, (SCM_obj *)code_ptr )) return 1;
- load_word( *(long *)code_ptr );
- code_ptr += 2;
- }
-
- else
- { os_err = "Procedure object format error"; return 1; }
- }
-
- }
-
- { long i, rest = len - ( ((long)code_ptr) - ((long)proc_adr) - 2 );
- if ((rest < 0L) || ((rest & 3L) != 0))
- { os_err = "Procedure object format error"; return 1; }
- for (i=rest/4; i>0; i--)
- { if (load_value( (SCM_obj *)code_ptr )) return 1;
- code_ptr += 2;
- }
- }
-
- /* do patchup for emulation code */
-
- if (patchup_M6